Skip to content

feat: add natural language log querying - #2

Merged
Aneeshie merged 2 commits into
mainfrom
feat/natural-language-querying
Jun 21, 2026
Merged

Aneeshie merged 2 commits into
mainfrom
feat/natural-language-querying

Conversation

@Aneeshie

@Aneeshie Aneeshie commented Jun 21, 2026 •

Copy link
Copy Markdown
Owner

Overview

This PR introduces natural language querying for Loom.

Users can now search logs using plain English instead of manually constructing filters and semantic search queries.

Examples

go run ./cmd/query --ask "show me authentication failures"

go run ./cmd/query --ask "show me database errors from the last hour"

go run ./cmd/query --ask "show me warning logs from auth service"

The query is interpreted by an LLM and translated into a structured query intent, which is then executed using Loom's existing filtering and semantic search pipeline.


Architecture

User Query
     |
     v
Natural Language Parser
     |
     v
QueryIntent
     |
     +-------------------+
     |                   |
     v                   v
GetLogs()          SimilarLogs()
     |
     v
Results

Example:

show me authentication failures

↓

{
  "query": "authentication",
  "level": "ERROR",
  "service": "",
  "host": "",
  "since": ""
}

↓

Semantic Search + ERROR Filter

↓

Invalid authentication token
User authorization denied

Changes

Added

  • internal/nlq package
  • QueryIntent model
  • IntentParser interface
  • OllamaParser implementation
  • --ask CLI flag
  • Intent → LogFilter conversion
  • Intent → Semantic Search conversion

Supported Intent Fields

{
  "query": "",
  "level": "",
  "service": "",
  "host": "",
  "since": ""
}

Query Routing

  • Uses SimilarLogs() when a semantic query is present
  • Falls back to GetLogs() for filter-only queries

Design Goals

  • Reuse existing hybrid search infrastructure
  • Avoid introducing new gRPC APIs
  • Avoid schema or database changes
  • Keep natural language processing entirely client-side
  • Allow future parser implementations without changing query execution logic

Example Queries

show me authentication failures

↓

{
  "query": "authentication",
  "level": "ERROR"
}
show me database errors from the last hour

↓

{
  "query": "database",
  "level": "ERROR",
  "since": "1h"
}
show me warning logs from auth service

↓

{
  "query": "",
  "level": "WARN",
  "service": "auth"
}

Future Improvements

  • Query explanation output
  • Similarity score display
  • Query reranking
  • Additional parser backends
  • NLQ evaluation tests
  • Natural language aggregations and analytics

Result

Loom now supports querying logs using plain English while reusing the existing filtering and hybrid semantic search infrastructure.

Summary by CodeRabbit

  • New Features

    • Added natural language query support via -ask CLI flag, enabling users to ask questions about logs in plain English.
  • Chores

    • Removed IDE configuration files from the repository.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Removes tracked .idea/ IDE configuration files and adds a natural-language query mode. A new internal/nlq package defines a QueryIntent struct, an IntentParser interface, and an OllamaParser that POSTs to a local Ollama instance to parse free-text questions into structured log filter intents. The cmd/query CLI gains an -ask flag that routes through this parser and dispatches to either semantic search or direct log filtering. A debug print is also added in SimilarLogs for filtered-out distance rows.

Changes

Natural-Language Query Feature

Layer / File(s) Summary
NLQ types and interface contract
internal/nlq/intent.go
Defines QueryIntent struct with JSON-tagged string fields (Query, Level, Service, Host, Since) and the IntentParser interface with a context-aware Parse method.
Ollama HTTP parser implementation
internal/nlq/ollama.go
Implements OllamaParser with NewOllamaParser, a Parse method that builds a structured prompt, substitutes the user query, POSTs to localhost:11434/api/generate, and unmarshals the JSON response into QueryIntent. Also includes a duplicate package-level callOllamaAPI that hardcodes the model and decodes a different response field.
CLI -ask flag, runNLQ, and debug output
cmd/query/main.go, internal/storage/postgres.go
Adds -ask CLI flag, updates main() to dispatch to runNLQ, which translates parsed intent fields into a pb.LogFilter and routes to runSemanticSearch or client.GetLogs. Adds a fmt.Printf in SimilarLogs for rows skipped by the distance threshold.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Aneeshie/Loom#1: The new -ask path calls runSemanticSearch, which relies on the SimilarLogs vector-embedding search introduced in this PR.

Poem

🐇 A rabbit asked: "Show me errors from last night!"
The Ollama model thought, then parsed it right,
With level, host, and service all aligned,
A LogFilter built from words so unconfined.
No SQL typed — just English, clean and bright! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding natural language log querying functionality, which is the primary objective across all file changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/natural-language-querying

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
cmd/query/main.go (2)

161-161: 💤 Low value

Consider making the model name configurable.

The model "llama3.2:3b" is hardcoded. A flag like --model would let users swap models without code changes (e.g., for faster inference or different capabilities).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/query/main.go` at line 161, The model name "llama3.2:3b" is hardcoded in
the NewOllamaParser function call on line 161. Add a command-line flag (such as
--model) to make the model name configurable, retrieve the flag value, and pass
it to NewOllamaParser instead of the hardcoded string. This allows users to
specify different models when running the command without modifying code.

228-235: ⚡ Quick win

Add "no logs found" feedback for empty results.

The main GetLogs path (line 96-102) prints "no logs found" when resp.Logs is nil, but runNLQ silently exits. For consistency and better UX, handle the empty case.

Proposed fix
+	if resp.Logs == nil || len(resp.Logs) == 0 {
+		fmt.Println("no logs found")
+		return
+	}
+
 	for _, logEntry := range resp.Logs {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/query/main.go` around lines 228 - 235, The for loop in runNLQ that
iterates over resp.Logs does not handle the empty case, whereas the main GetLogs
path (lines 96-102) prints "no logs found" when resp.Logs is nil or empty. Add a
check before the for loop in runNLQ to print "no logs found" when resp.Logs is
empty or nil, ensuring consistent user feedback between both code paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/query/main.go`:
- Around line 186-200: The time.ParseDuration function does not support day
units like "7d" that the LLM parser may output, causing silent failures where
the StartTime filter remains unset. Before calling time.ParseDuration on
intent.Since, add preprocessing logic to normalize day units by converting
patterns like "7d" to their equivalent hour format (e.g., "168h") using string
manipulation. This requires parsing the duration string to identify day unit
suffixes and converting them to supported units before passing to
time.ParseDuration. Consider using strings and strconv packages to handle this
conversion, and optionally warn the user if the parsing still fails after
normalization.

In `@internal/nlq/ollama.go`:
- Around line 193-205: After calling client.Do(req) and checking for error, you
must also validate the HTTP status code from the response before attempting to
decode the JSON. Add a check after defer resp.Body.Close() to verify that
resp.StatusCode indicates success (check if it's in the 2xx range). If the
status code indicates an error, return an error immediately with details about
the HTTP status and optionally the response body. Only proceed to the
json.NewDecoder(resp.Body).Decode(&res) call if the status code check passes.
This ensures actual server errors are properly surfaced instead of confusing
JSON unmarshal errors.
- Around line 210-239: The callOllamaAPI function is unused in the codebase and
has an inconsistent JSON field mapping compared to its method counterpart—it
decodes "output" instead of "response", which would cause it to silently return
empty strings when calling Ollama's API. Remove the entire callOllamaAPI
function definition since it is not being called anywhere and relies on the
incorrect JSON field name.
- Around line 160-196: The HTTP client created in the callOllamaAPI function
lacks a timeout configuration, which can cause indefinite blocking if Ollama
becomes unresponsive. Add "time" to the imports at the top of the file, then
modify the client initialization from http.Client{} to include a Timeout field
set to an appropriate duration value (e.g., 30 seconds or similar) using
time.Duration to prevent requests from hanging indefinitely.
- Around line 145-146: Remove the two debug fmt.Println statements that output
raw LLM responses to stdout. Locate the lines containing fmt.Println("RAW OLLAMA
RESPONSE:") and fmt.Println(resp) in the ollama.go file and delete both
statements entirely, as debug output should not be present in production code.

In `@internal/storage/postgres.go`:
- Around line 217-222: Remove the fmt.Printf debug output statement that prints
distance and message fields in the storage layer. This unstructured output
pollutes server stdout and exposes potentially sensitive log content. If debug
logging is needed for development, replace it with a proper structured logging
call at an appropriate debug level that respects the application's logging
configuration, otherwise delete the fmt.Printf block entirely.

---

Nitpick comments:
In `@cmd/query/main.go`:
- Line 161: The model name "llama3.2:3b" is hardcoded in the NewOllamaParser
function call on line 161. Add a command-line flag (such as --model) to make the
model name configurable, retrieve the flag value, and pass it to NewOllamaParser
instead of the hardcoded string. This allows users to specify different models
when running the command without modifying code.
- Around line 228-235: The for loop in runNLQ that iterates over resp.Logs does
not handle the empty case, whereas the main GetLogs path (lines 96-102) prints
"no logs found" when resp.Logs is nil or empty. Add a check before the for loop
in runNLQ to print "no logs found" when resp.Logs is empty or nil, ensuring
consistent user feedback between both code paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee5da874-e538-4ea0-83e1-f33d84d12474

📥 Commits

Reviewing files that changed from the base of the PR and between cf46749 and b6624d7.

📒 Files selected for processing (9)
  • .idea/.gitignore
  • .idea/go.imports.xml
  • .idea/loom.iml
  • .idea/modules.xml
  • .idea/vcs.xml
  • cmd/query/main.go
  • internal/nlq/intent.go
  • internal/nlq/ollama.go
  • internal/storage/postgres.go
💤 Files with no reviewable changes (5)
  • .idea/loom.iml
  • .idea/go.imports.xml
  • .idea/vcs.xml
  • .idea/modules.xml
  • .idea/.gitignore

Comment thread cmd/query/main.go
Comment on lines +186 to +200
if intent.Since != "" {

duration, err := time.ParseDuration(
intent.Since,
)

if err == nil {

start := time.Now().
Add(-duration).
Unix()

filter.StartTime = &start
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does Go time.ParseDuration support day units like 7d?

💡 Result:

No, Go's time.ParseDuration function does not support "d" (day) or any units larger than hours [1][2][3]. The valid unit suffixes supported by time.ParseDuration are [1][2]: - ns (nanoseconds) - us or µs (microseconds) - ms (milliseconds) - s (seconds) - m (minutes) - h (hours) The Go language designers intentionally omitted units for days or larger intervals to avoid the ambiguity caused by daylight savings time transitions and varying day lengths [4][5][6]. If you need to represent a duration in days, you should convert it to hours (e.g., use "72h" instead of "3d" or "7d") [3][5].

Citations:


🏁 Script executed:

# First, check if the file exists and inspect the relevant lines
cd /
find . -name "main.go" -path "*/cmd/query/*" 2>/dev/null | head -5

Repository: Aneeshie/Loom

Length of output: 95


🏁 Script executed:

# Count lines in the file to understand its size
wc -l cmd/query/main.go

Repository: Aneeshie/Loom

Length of output: 79


🏁 Script executed:

# Read the specific section mentioned (lines 186-200)
sed -n '186,200p' cmd/query/main.go

Repository: Aneeshie/Loom

Length of output: 255


🏁 Script executed:

# Check the broader context around runNLQ function and the LLM prompt
sed -n '155,236p' cmd/query/main.go

Repository: Aneeshie/Loom

Length of output: 1166


🏁 Script executed:

# Check the imports to see what's available
sed -n '1,30p' cmd/query/main.go

Repository: Aneeshie/Loom

Length of output: 931


time.ParseDuration does not support day units ("7d").

The LLM parser likely outputs durations like "7d" for natural language queries such as "last week", but Go's time.ParseDuration only supports ns, us, ms, s, m, h. When parsing fails, the error is silently ignored (lines 192–193), causing the StartTime filter to remain unset.

Either normalize day units (e.g., convert "7d" to "168h") before parsing or warn the user when parsing fails.

Proposed fix — convert days to hours before parsing
 	if intent.Since != "" {
+		// Normalize day units to hours (time.ParseDuration doesn't support "d")
+		since := intent.Since
+		if strings.HasSuffix(since, "d") {
+			daysStr := strings.TrimSuffix(since, "d")
+			if days, err := strconv.Atoi(daysStr); err == nil {
+				since = fmt.Sprintf("%dh", days*24)
+			}
+		}
 
 		duration, err := time.ParseDuration(
-			intent.Since,
+			since,
 		)
 
-		if err == nil {
-
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "warning: could not parse duration %q: %v\n", intent.Since, err)
+		} else {
 			start := time.Now().
 				Add(-duration).
 				Unix()
-
 			filter.StartTime = &start
 		}
 	}

Add imports for strconv, strings, and os.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/query/main.go` around lines 186 - 200, The time.ParseDuration function
does not support day units like "7d" that the LLM parser may output, causing
silent failures where the StartTime filter remains unset. Before calling
time.ParseDuration on intent.Since, add preprocessing logic to normalize day
units by converting patterns like "7d" to their equivalent hour format (e.g.,
"168h") using string manipulation. This requires parsing the duration string to
identify day unit suffixes and converting them to supported units before passing
to time.ParseDuration. Consider using strings and strconv packages to handle
this conversion, and optionally warn the user if the parsing still fails after
normalization.

Comment thread internal/nlq/ollama.go
Comment on lines +145 to +146
fmt.Println("RAW OLLAMA RESPONSE:")
fmt.Println(resp)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove debug print statements.

These fmt.Println calls output raw LLM responses to stdout in production, which pollutes CLI output and may leak user query context.

Proposed fix
-	fmt.Println("RAW OLLAMA RESPONSE:")
-	fmt.Println(resp)
-
 	var intent QueryIntent
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt.Println("RAW OLLAMA RESPONSE:")
fmt.Println(resp)
var intent QueryIntent
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/nlq/ollama.go` around lines 145 - 146, Remove the two debug
fmt.Println statements that output raw LLM responses to stdout. Locate the lines
containing fmt.Println("RAW OLLAMA RESPONSE:") and fmt.Println(resp) in the
ollama.go file and delete both statements entirely, as debug output should not
be present in production code.

Comment thread internal/nlq/ollama.go
Comment on lines +160 to +196
func (p *OllamaParser) callOllamaAPI(
ctx context.Context,
prompt string,
) (string, error) {

client := &http.Client{}

payload := map[string]any{
"model": p.model,
"prompt": prompt,
"stream": false,
}

body, err := json.Marshal(payload)
if err != nil {
return "", err
}

req, err := http.NewRequestWithContext(
ctx,
"POST",
"http://localhost:11434/api/generate",
bytes.NewBuffer(body),
)
if err != nil {
return "", err
}

req.Header.Set(
"Content-Type",
"application/json",
)

resp, err := client.Do(req)
if err != nil {
return "", err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add HTTP client timeout to prevent hanging on unresponsive Ollama.

The HTTP client has no timeout configured. LLM inference can be slow, and if Ollama is unresponsive, this will block indefinitely without any indication to the user.

Proposed fix
 func (p *OllamaParser) callOllamaAPI(
 	ctx context.Context,
 	prompt string,
 ) (string, error) {
 
-	client := &http.Client{}
+	client := &http.Client{
+		Timeout: 120 * time.Second,
+	}

Add "time" to the imports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/nlq/ollama.go` around lines 160 - 196, The HTTP client created in
the callOllamaAPI function lacks a timeout configuration, which can cause
indefinite blocking if Ollama becomes unresponsive. Add "time" to the imports at
the top of the file, then modify the client initialization from http.Client{} to
include a Timeout field set to an appropriate duration value (e.g., 30 seconds
or similar) using time.Duration to prevent requests from hanging indefinitely.

Comment thread internal/nlq/ollama.go
Comment on lines +193 to +205
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

var res struct {
Response string `json:"response"`
}

if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return "", err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Check HTTP status code before decoding response.

If Ollama returns an error (4xx/5xx), the code attempts JSON decode anyway, producing a confusing unmarshal error instead of surfacing the actual failure.

Proposed fix
 	resp, err := client.Do(req)
 	if err != nil {
 		return "", err
 	}
 	defer resp.Body.Close()
 
+	if resp.StatusCode != http.StatusOK {
+		return "", fmt.Errorf("ollama API error: status %d", resp.StatusCode)
+	}
+
 	var res struct {
 		Response string `json:"response"`
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var res struct {
Response string `json:"response"`
}
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return "", err
}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("ollama API error: status %d", resp.StatusCode)
}
var res struct {
Response string `json:"response"`
}
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return "", err
}
🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 197-197: Error return value of resp.Body.Close is not checked

(errcheck)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/nlq/ollama.go` around lines 193 - 205, After calling client.Do(req)
and checking for error, you must also validate the HTTP status code from the
response before attempting to decode the JSON. Add a check after defer
resp.Body.Close() to verify that resp.StatusCode indicates success (check if
it's in the 2xx range). If the status code indicates an error, return an error
immediately with details about the HTTP status and optionally the response body.
Only proceed to the json.NewDecoder(resp.Body).Decode(&res) call if the status
code check passes. This ensures actual server errors are properly surfaced
instead of confusing JSON unmarshal errors.

Comment thread internal/nlq/ollama.go
Comment on lines +210 to +239
func callOllamaAPI(ctx context.Context, prompt string) (string, error) {
client := &http.Client{}
payload := map[string]string{
"model": "llama3.2:3b",
"prompt": prompt,
}
body, _ := json.Marshal(payload)

req, err := http.NewRequestWithContext(ctx, "POST", "http://localhost:11434/api/generate", bytes.NewBuffer(body))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")

resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

var res struct {
Output string `json:"output"`
}

if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return "", err
}

return res.Output, nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove unused callOllamaAPI function.

This standalone function is unused and inconsistent with the method version—it decodes "output" (line 231) instead of "response" (line 200), which would silently return empty strings from Ollama's actual API.

Proposed fix
-func callOllamaAPI(ctx context.Context, prompt string) (string, error) {
-	client := &http.Client{}
-	payload := map[string]string{
-		"model":  "llama3.2:3b",
-		"prompt": prompt,
-	}
-	body, _ := json.Marshal(payload)
-
-	req, err := http.NewRequestWithContext(ctx, "POST", "http://localhost:11434/api/generate", bytes.NewBuffer(body))
-	if err != nil {
-		return "", err
-	}
-	req.Header.Set("Content-Type", "application/json")
-
-	resp, err := client.Do(req)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	var res struct {
-		Output string `json:"output"`
-	}
-
-	if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
-		return "", err
-	}
-
-	return res.Output, nil
-}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func callOllamaAPI(ctx context.Context, prompt string) (string, error) {
client := &http.Client{}
payload := map[string]string{
"model": "llama3.2:3b",
"prompt": prompt,
}
body, _ := json.Marshal(payload)
req, err := http.NewRequestWithContext(ctx, "POST", "http://localhost:11434/api/generate", bytes.NewBuffer(body))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var res struct {
Output string `json:"output"`
}
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return "", err
}
return res.Output, nil
}
🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 228-228: Error return value of resp.Body.Close is not checked

(errcheck)


[error] 210-210: func callOllamaAPI is unused

(unused)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/nlq/ollama.go` around lines 210 - 239, The callOllamaAPI function is
unused in the codebase and has an inconsistent JSON field mapping compared to
its method counterpart—it decodes "output" instead of "response", which would
cause it to silently return empty strings when calling Ollama's API. Remove the
entire callOllamaAPI function definition since it is not being called anywhere
and relies on the incorrect JSON field name.

Source: Linters/SAST tools

Comment on lines +217 to +222
fmt.Printf(
"distance=%.4f message=%s\n",
distance,
logEntry.Message,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove server-side debug output.

This fmt.Printf runs in the storage layer for every matched log, polluting server stdout and potentially exposing sensitive log message content. Debug output should use structured logging with appropriate levels, or be removed before merge.

Proposed fix
 		if distance > SIMILARITY_THRESHOLD {
 			continue
 		}
 
-		fmt.Printf(
-			"distance=%.4f message=%s\n",
-			distance,
-			logEntry.Message,
-		)
-
 		logs = append(logs, logEntry)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt.Printf(
"distance=%.4f message=%s\n",
distance,
logEntry.Message,
)
if distance > SIMILARITY_THRESHOLD {
continue
}
logs = append(logs, logEntry)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/storage/postgres.go` around lines 217 - 222, Remove the fmt.Printf
debug output statement that prints distance and message fields in the storage
layer. This unstructured output pollutes server stdout and exposes potentially
sensitive log content. If debug logging is needed for development, replace it
with a proper structured logging call at an appropriate debug level that
respects the application's logging configuration, otherwise delete the
fmt.Printf block entirely.

@Aneeshie
Aneeshie merged commit 8827fbc into main Jun 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant